package com.yaolisheng.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;


/**
 * @author : yaols
 * Desc:
 * Company: 神州数码信息系统有限公司
 * Date: 2022/11/04 20:34
 */

@Configuration
@EnableAsync
@Slf4j
public class ThreadPoolConfig {

    /**
     * 核心线程数
     */
    @Value("${async.executor.thread.core_pool_size}")
    private Integer corePoolSize;

    /**
     * 最大线程数
     */
    @Value("${async.executor.thread.max_pool_size}")
    private Integer maxPoolSize;

    /**
     * 队列大小
     */
    @Value("${async.executor.thread.queue_capacity}")
    private Integer queueCapacity;

    /**
     * 队列大小
     */
    @Value("${async.executor.thread.keep_alive_seconds}")
    private Integer keepAliveSeconds;

    /**
     * 线程池中线程名称前缀
     */
    @Value("${async.executor.thread.name.prefix}")
    private String namePrefix;

    @Bean(name = "asyncServiceExecutor")
    public ExecutorService getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程数
        executor.setCorePoolSize(corePoolSize);
        //最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //任务队列的大小
        executor.setQueueCapacity(queueCapacity);
        //线程前缀名
        executor.setThreadNamePrefix(namePrefix);
        //线程存活时间
        executor.setKeepAliveSeconds(keepAliveSeconds);

        /**
         * 拒绝处理策略
         * CallerRunsPolicy()：交由调用方线程运行，比如 main 线程。
         * AbortPolicy()：直接抛出异常。
         * DiscardPolicy()：直接丢弃。
         * DiscardOldestPolicy()：丢弃队列中最老的任务。
         */
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        //线程初始化
        executor.initialize();
        return executor.getThreadPoolExecutor();
    }

    /**
     * 异步任务中异常处理
     *
     * @return
     */

    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (ex, method, params) -> {
            log.error("==========================" + ex.getMessage() + "=======================", ex);
            log.error("exception method:" + method.getName());
        };
    }
}
